package cn.ratel.tool;

import cn.ratel.aop.ProxyKit;
import cn.ratel.aop.annotation.Clear;
import cn.ratel.aop.annotation.Enhancer;
import cn.ratel.component.Enhancers;
import com.google.common.base.Preconditions;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class EnhancersBuilder {

	public static List<Enhancers.Enhancer> build(List<Enhancers.Enhancer> globalEnhancers, Class<?> clazz, Method method) {
		List<Enhancers.Enhancer> result = new ArrayList<>();
		result.addAll(globalEnhancers);
		result = add(clazz.getAnnotation(Clear.class), clazz.getAnnotation(Enhancer.class), result);
		result = add(method.getAnnotation(Clear.class), method.getAnnotation(Enhancer.class), result);
		return result.stream().distinct().collect(Collectors.toList());
	}

	private static List<Enhancers.Enhancer> add(Clear clear, Enhancer enhancer, List<Enhancers.Enhancer> result) {
		if (clear != null) {
			Class<? extends Enhancers.Enhancer>[] clearClasses = clear.value();
			if (clearClasses.length == 0) {
				result.clear();
			} else {
				for (Class<? extends Enhancers.Enhancer> clearClass : clearClasses) {
					Iterator<Enhancers.Enhancer> iterator = result.iterator();
					while (iterator.hasNext()) {
						Class<?> realClass = iterator.next().getClass();
						if (realClass == clearClass) {
							iterator.remove();
						}
					}
				}
			}
		}
		if (enhancer != null) {
			Class<? extends Enhancers.Enhancer>[] value = enhancer.value();
			Preconditions.checkNotNull(value);
			for (Class<? extends Enhancers.Enhancer> clazz : value) {
				result.add(ProxyKit.instance(clazz));
			}
		}
		return result;
	}
}
